import type { ComponentDefinitionItem, ComponentMeta } from '@/definitions/type'
import { matchComponentMeta } from '@/definitions/match'
import { arrayMoveMutable } from 'array-move'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

interface ToggleGlobalSpin {
  (tip?: string): void
  (spinning: boolean, tip?: string): void
  spinningCount: number
}
/** global config for designer */
interface Config {
  /** 属性面板配置 */
  attrToggler: {
    /** @default false */
    collapsed: boolean
    /** @default true */
    clickRenderToOpen: boolean
  }
  /** 侧边栏面板配置 */
  asideToggler: {
    /** @default false */
    collapsed: boolean
  }
  platform: 'pc' | 'mobile'
  preview: {
    /** @default false */
    open: boolean
  }
  spin: {
    /** @default false */
    spinning: boolean
    tip?: string
  }
}
function getInitialConfig(): Config {
  return {
    attrToggler: {
      collapsed: false,
      clickRenderToOpen: true,
    },
    asideToggler: {
      collapsed: false,
    },
    platform: 'mobile',
    preview: {
      open: false,
    },
    spin: {
      spinning: false,
    },
  }
}
export const useDesignStore = defineStore('design', () => {
  const config = ref<Config>(getInitialConfig())
  const activeRender = ref<Nullable<ComponentMeta>>(null)
  const renders = ref<ComponentMeta[]>([])
  function handleRenderAction(action: 'up' | 'down' | 'delete', render?: Nullable<ComponentMeta>) {
    render ??= activeRender.value
    if (render && renders.value.length > 0) {
      const currentIndex = renders.value.findIndex(r => r.id === render.id)
      if (~currentIndex) {
        if (action === 'up') {
          if (currentIndex === 0)
            return
          arrayMoveMutable(renders.value, currentIndex, currentIndex - 1)
        }
        else if (action === 'down') {
          if (currentIndex === renders.value.length - 1)
            return
          arrayMoveMutable(renders.value, currentIndex, currentIndex + 1)
        }
        else if (action === 'delete') {
          renders.value.splice(currentIndex, 1)
          if (render === activeRender.value) {
            activeRender.value = null
          }
        }
      }
    }
  }
  function customDragClone(element: ComponentDefinitionItem) {
    return matchComponentMeta(element)
  }
  function setActiveRender(render: ComponentMeta) {
    activeRender.value = render
    if (config.value.attrToggler.clickRenderToOpen) {
      config.value.attrToggler.collapsed = false
    }
  }
  function unsetActiveRender() {
    activeRender.value = null
  }
  const attrTogglerOpened = computed(() => !config.value.attrToggler.collapsed)
  const asideTogglerOpened = computed(() => !config.value.asideToggler.collapsed)
  function toggleAttrToggler() {
    config.value.attrToggler.collapsed = !config.value.attrToggler.collapsed
  }
  function toggleAsideToggler() {
    config.value.asideToggler.collapsed = !config.value.asideToggler.collapsed
  }
  function setPlatform(platform: Config['platform']) {
    config.value.platform = platform
  }
  function togglePreview(open: boolean) {
    config.value.preview.open = open
  }
  const toggleGlobalSpin: ToggleGlobalSpin = function toggleGlobalSpin(...args: unknown[]) {
    let spinning: boolean
    let tip: string
    if (typeof args[0] === 'boolean') {
      spinning = args[0]
      tip = args[1] as string
      toggleGlobalSpin.spinningCount += spinning ? 1 : -1
      config.value.spin.spinning = toggleGlobalSpin.spinningCount > 0
    }
    else {
      tip = args[0] as string
    }
    config.value.spin.tip = tip
  }
  toggleGlobalSpin.spinningCount = 0
  function clear() {
    unsetActiveRender()
    renders.value.length = 0
  }
  return {
    config,
    activeRender,
    renders,
    handleRenderAction,
    customDragClone,
    setActiveRender,
    unsetActiveRender,
    toggleAttrToggler,
    toggleAsideToggler,
    attrTogglerOpened,
    asideTogglerOpened,
    setPlatform,
    togglePreview,
    toggleGlobalSpin,
    clear,
  }
})
